/*
 * @name ajaxLib.js
 * @author : Amissah Gideon<kuulmek@yahoo.com>
 * @version 1.0
 */

Number.prototype.formatMoney = function (c, d, t) {
    var n = this, c = isNaN(c = Math.abs(c)) ? 2 : c, d = d == undefined ? "," : d, t = t == undefined ? "." : t, s = n < 0 ? "-" : "", i = parseInt(n = Math.abs(+n || 0).toFixed(c)) + "", j = (j = i.length) > 3 ? j % 3 : 0;
    return s + (j ? i.substr(0, j) + t : "") + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + t) + (c ? d + Math.abs(n - i).toFixed(c).slice(2) : "");
};


/*******************************************************************************
 *            COLLECTIONS CLASS
 ******************************************************************************/
function Collection(data) {
    this.list = {};
    this.size = 0;
    this.callbacks = {
        add:[],
        remove:[]
    };

    if (data) {
        var self = this;
        $.each(data, function (k, v) {
            self.add(k, v);
        });
    }
}

Collection.prototype.registerCallback = function (type, callback) {
    var self = this;
    if (typeof self.callbacks[type] != 'undefined') {
        self.callbacks[type].push(callback);
    }
}

Collection.prototype.fireCallbacks = function (type, key, value) {
    var self = this;
    for (var i = 0; i < self.callbacks[type].length; i++) {
        self.callbacks[type][i](key, value);
    }
}

/**
 * Adds a new object to the collection if the key for the object does not already exist
 * @param key the collection key
 * @param value the value to add
 **/
Collection.prototype.add = function (key, value) {
    var self = this;
    if (typeof self.list[key] == 'undefined') {
        self.list[key] = value;
        self.size++;

        self.fireCallbacks('add', key, value);
    }
}
/**
 * Removes the object identified by the key from the collection
 * @param key the search key
 **/
Collection.prototype.remove = function (key) {
    var self = this;
    if (typeof self.list[key] != 'undefined') {
        var value = self.list[key];
        delete self.list[key];
        self.size--;

        self.fireCallbacks('remove', key, value);
    }
}

/**
 * Returns the values stored for this key
 * @param key the search key
 **/
Collection.prototype.get = function (key) {
    var self = this;
    // if the a valid key is specified
    if (self.list.hasOwnProperty(key)) {
        return self.list[key];
    }
    // if the key specified is a number, then we may be looking for an element at a specified index
    if (!isNaN(parseInt(key))) {
        var index = 0;
        for (var k in self.list) {
            if (index == key) {
                return self.list[k];
            }
            index++;
        }
    }
    return null;
}

/**
 * Replaces or adds a new value to the map
 * @param key the key for the value
 * @param value the value to add
 */
Collection.prototype.set = function (key, value) {
    var self = this;
    self.list[key] = value;
}

/**
 * Returns the list of items stored in this collection
 * @return the list of items as an object
 */
Collection.prototype.getList = function () {
    var self = this;
    return self.list;
};

/**
 * Returns the count of the number items in this collection
 * @return number of items in this collection
 */
Collection.prototype.getSize = function () {
    var self = this;
    return self.size;
};

Collection.prototype.iterate = function (callback) {
    var self = this;
    for (var index in self.list) {
        if (typeof callback == "function") {
            callback.apply(self, [index, self.list[index]]);
        }
    }
};

Collection.prototype.getKeys = function () {
    var self = this;
    var keys = [];
    keys = Object.keys(self.list);
    return keys;
};

/**
 * Resets the list to an empty object
 */
Collection.prototype.clear = function () {
    var self = this;
    self.list = {};
}

/*******************************************************************************
 *            END OF COLLECTIONS CLASS
 ******************************************************************************/

/*******************************************************************************
 * Multifunctional Javascript Object to be used for common task accross the site
 ******************************************************************************/
var Jlib = {
    
    dialog: null,
    dialogCanClose: false,
    
    /* Function init
     * This function is the entry point of the Object.
     * @return void
     * @access public
     * */
    init: function() {
        var self = this;
        
        $("#loader_bar").ajaxStart(function () {
            $(this).show();
        });
        
        $("#loader_bar").ajaxStop(function () {
            $(this).hide();
        });
        
        // configure dialogs
        this.setupDialog();
    },
    
    /**
     * Sets up the general library dialog for use by the <code>showDialog</code>
     * and related functions
     */
    setupDialog: function() {
        var self = this;
        
        this.dialog = $("#core_dialog").dialog({
            autoOpen: false,
            width: '700',
            height: '400',
            modal: true
        });
        
        $("#submit_frame").load(function(e) {
            e.preventDefault();

            if( self.dialogCanClose ) {
                self.dialog.dialog('close');
                self.dialogCanClose = false;
                
                window.history.go(0);
            }
        });
        
        $(".dialog_opener").live('click', function(e) {
            e.preventDefault();
          
            var $opener = $(this);
            var url = $opener.attr("href") || $opener.data('url');
            var title = $opener.attr("title");
            var callback = $opener.data("callback");
            var load = $opener.data('load-callback');
            
            $.get(url, function(content) {
                self.showDialog({
                    title: title, 
                    content: content,
                    width: $opener.data('width'),
                    height: $opener.data('height'),
                    load: load,
                    close: callback
                });
            });
        });
    },
    
    /**
     * Creates and displays a Popup Dialog in the center of the screen using the options
     * provided
     * 
     * @param options
     */
    showDialog: function(options) {
        var self = this;

        var _options = {
            title: 'Dialog Title',
            content: '<div></div>',
            height: 400,
            width: 700,
            load: function() {},
            close: function() {},
            buttons: {
                'Cancel': function() {
                    Jlib.closeDialog();
                }
            }
        };
        
        $.extend(true, _options, options);
        
        // remove any previously bound functions
        this.dialog.unbind('dialogopen');
        
        // bind load event
        if( $.isFunction(_options['load']) ) {
            this.dialog.bind('dialogopen', _options['load']);
        }
        
        else {
            this.dialog.bind('dialogopen', function() {
                self.executeFunction( _options['load'] ); 
            });
        }
        
        $("#core_dialog").html( _options['content'] );
        
        this.dialog.dialog("option","title", _options['title']);
        this.dialog.dialog("option","height", parseInt(_options['height']));
        this.dialog.dialog("option","width", parseInt(_options['width']));
        this.dialog.dialog("option","buttons", _options['buttons']);
        
        this.dialog.parents(".ui-dialog").find("button").addClass("btn");
        
        this.dialog.dialog("open");
        
        //$("#core_dialog .chosen").chosen();
        
        $("#core_dialog #cancel-form").click(function() {
            self.dialog.dialog('close');
        });

        $("#core_dialog form").submit(function(e) {
            
            if( this.checkValidity && !this.checkValidity() ) { 
                return false;
            }
                    
            self.dialogCanClose = true;
                
            var url = $(this).attr("action");
            var query = $(this).serialize();
            
            $.ajax({
                url: url,
                data: query,
                type: 'post',
                success: function(data) {
                    self._handleFormSubmit(data, _options['close']);
                },
                error: function(xhr) {
                    console.log(xhr.responseText);
                }
            });
                
            self.closeDialog();

            return false;
        }); 
    },
    
    /**
     * Submits any form contained inside the dialog
     */ 
    submitDialog: function() {
        this.dialog.find("form").submit();
    },
    
    /**
     * Hides the general library dialog
     */
    closeDialog: function() {
        this.dialog.dialog('close');
    },
    
    /**
     * Makes an AJAX Post Request to the supplied URL and loads the content in a Dialog
     * using the supplied options 
     * 
     * @param url
     * @param options
     */
    openInDialog: function(url, options) {
        $.ajax({
            url: url,
            type: 'post',
            success: function(data) {
                var _default = $.extend(options, {
                    content: data
                });
                
                Jlib.showDialog(_default);
            },
            error: function(xhr) {
                console.log(xhr.responseText);
                alert("Failed To Open " + url);
            }
        });
    },
    
    _handleFormSubmit: function(data, callback) {
        // if the response is in valid JSON, parse it so it can be used
        // in the callback as necessary
        try {
            data = JSON.parse(data);
        } catch(e) {}

        if( callback && $.isFunction(callback) ) {
            callback(data);
        }

        else if ( callback && typeof callback === "string" ) {
            this.executeFunctionByName(callback, window, data);
        }
    },
        
    executeFunctionByName: function(functionName, context /*, args */) {
            
        if( !context ) {
            context = window;
        }
            
        var args = Array.prototype.slice.call(arguments).splice(2);
        var namespaces = functionName.split(".");
        var func = namespaces.pop();
        for(var i = 0; i < namespaces.length; i++) {
            context = context[namespaces[i]];
        }
        
        if( !context[func] ) {
            console.log(func + " cannot be found in the " + context + " context");
            return false;
        }
        
        return context[func].apply(this, args);
    },
    
    executeFunction: function(func /*, args */) {
        
        if( func && typeof func == "string" ) {
            this.executeFunctionByName(func, window, args);
        }
        
        else if( func && $.isFunction(func) ) {
            var args = Array.prototype.slice.call(arguments).splice(1);
            func.apply(this, args);
        }
    },


    /*Universal Delete for all Main record DataTable*/
    do_delete:function (griObject,url, grid, callback) {
        var self = this;
        var row_ids = FlexObject.getSelectedRowIds(grid);

        jConfirm('Are you sure you want to continue ?', 'Confirm', function(confirmation) {
            if(confirmation){
                $.post(url, {'ids[]': row_ids},function(response){
                    //delete was successful, remove checkbox rows
                    if(response.code == 0){
                        FlexObject.removeGridRows(grid);
                        griObject.flexNotify('Delete',response.msg,'success');
                        if(typeof callback == 'function'){
                            callback();
                        }
                    }
                    else if(response.code == 1){
                        griObject.flexNotify('Delete',response.msg,'error');
                    }
                },"json");
            }
        });
    },


    /*Universal Delete for all Main record DataTable*/
    do_sub_delete:function (griObject,url, grid, callback) {
        var self = this;
        var row_ids = FlexObject.getSelectedSubRowIds(grid);

        jConfirm('Are you sure you want to continue ?', 'Confirm', function(confirmation) {
            if(confirmation){
                $.post(url, {'ids[]': row_ids},function(response){
                    //delete was successful, remove checkbox rows
                    if(response.code == 0){
                        FlexObject.removeSubGridRows(grid);
                        griObject.flexNotify('Delete',response.msg,'success');
                        if(typeof callback == 'function'){
                            callback();
                        }
                    }
                    else if(response.code == 1){
                        griObject.flexNotify('Delete',response.msg,'error');
                    }
                },"json");
            }
        });
    },

    message: function(title, txt, type ,callback){
        var self = this;
        var cl = '';
        //if modal exist close it and call new one
        var visible = $('#modal_notify').is(':visible');
        if(visible){
            $("#modal_notify a.close").click();
        }

        if(!type){
            type = 'info';
        }

        if(type == 'success'){
            cl = 'alert-success';
        }
        else if(type == 'warning'){
            cl = 'alert-gradient';
        }
        else if(type == 'error'){
            cl = 'alert-error';
        }
        else if(type == 'info'){
            cl = 'alert-info';
        }

        var msg = "<div id='modal_notify' class='alert "+cl+"' style='position: fixed; z-index: 9999; width:500px; left: 50%; margin-left: -250px; top: 180px;'>";
        msg += "<a class='close' data-dismiss='alert' style='opacity: 1; line-height: 16px;' href='#'>✕</a>";
        msg += "<h4 class='alert-heading'>"+title+"</h4>";
        msg += "<span><div id='flashMessage' class='message'>"+txt+"</div></span>";
        msg += "</div>";

        self.modal_blanket_show();
        $('body').append(msg);

        $("#modal_notify a.close").click(function(){
            self.modal_blanket_hide();
            if(typeof callback == 'function'){
                callback();
            }
        });
    },

    modal_blanket_show:function(){
        $("#modal_blanket").show();
    },

    modal_blanket_hide:function(){
        $("#modal_blanket").hide();
    },

    serverError:function (text) {
        var self = this;
        //first hide modal loader if any
        //self.hideFormLoading();
        if (typeof text == 'undefined') {
            text = "Error while contacting server, please reload the page.";
        }

        self.message('Server Error',text, 'error');
    }

};

/* when the page is loaded */
$(document).ready(function () {
    Jlib.init();
});